﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XXF.BaseService.ServiceCenter.SystemRuntime;
using ZooKeeperNet;

namespace XXF.BaseService.ServiceCenter.ZK
{
    public abstract class ZKBase : IWatcher, IDisposable
    {
        protected ZooKeeper _zk;
        protected object _lockcreate = new object();
        protected const string root = "/dydservicecenter"; //根
        protected const string servicepathformat = root + "/{0}";//dydservicecenter/servicenamespace
        protected const string nodepathformat = root + "/{0}/{1}";//dydservicecenter/servicenamespace/sessionid

        public void CreateRoot()
        {
            try
            {
                // 创建一个与服务器的连接
                var zk = GetZookeeper();
                var stat = zk.Exists(root, false);
                if (stat == null)
                {
                    // 创建根节点
                    zk.Create(root, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent);
                }
            }
            catch (Exception exp)
            {
                throw new ServiceCenterException(string.Format("创建zookeeper根节点{0}出错", root), exp);
            }
        }

        protected string GetRootPath() { return root; }

        protected string GetServicePath(int serviceid)
        {
            return string.Format(servicepathformat, serviceid);
        }

        protected string GetNodePath(int serviceid, long sessionid)
        {
            return string.Format(nodepathformat, serviceid, sessionid);
        }

        protected ZKPathInfo GetPathInfo(string path)
        {
            if (string.IsNullOrWhiteSpace(path))
                return null;
            string[] ps = path.Trim('/').Split('/');
            if (ps.Length == 3)
            {
                return new ZKPathInfo() { ServiceId = Convert.ToInt32(ps[1]), SessionId = Convert.ToInt64(ps[2]), Type = ZKType.Node };
            }
            if (ps.Length == 2)
            {
                return new ZKPathInfo() { ServiceId = Convert.ToInt32(ps[1]), SessionId = 0, Type = ZKType.Service };
            }
            if (ps.Length == 1)
            {
                return new ZKPathInfo() { ServiceId = 0, SessionId = 0, Type = ZKType.Root };
            }
            return null;
        }

        public ZooKeeper GetZookeeper()
        {
            try
            {
                if (_zk != null && _zk.State != ZooKeeper.States.CLOSED)
                {
                    return _zk;
                }
                lock (_lockcreate)
                {
                    if (_zk == null)
                    {
                        if (string.IsNullOrWhiteSpace(SystemConfigHelper.ZooKeeperServer))
                            throw new ServiceCenterException("ZooKeeper服务连接为空");
                        _zk = new ZooKeeper(SystemConfigHelper.ZooKeeperServer, TimeSpan.FromSeconds(40), this);
                    }
                }
                return _zk;
            }
            catch (Exception exp)
            {
                throw new ServiceCenterException("创建zookeeper连接出错", exp);
            }
        }

        /// <summary>
        /// zookeeper节点的监视器
        /// </summary>
        public virtual void Process(WatchedEvent @event)
        {
            System.Diagnostics.Debug.Write(@event.Type.ToString() + " " + @event.Path);
        }

        public virtual void Dispose()
        {
            try
            {
                if (_zk != null)
                {
                    _zk.Dispose();
                }
            }
            catch { }
        }
    }

    public class ZKPathInfo
    {
        public ZKType Type { get; set; }
        public int ServiceId { get; set; }
        public long SessionId { get; set; }
    }

    public enum ZKType
    {
        Root,
        Service,
        Node,
    }
}
